﻿using System;
using System.Globalization;
using System.Text;
using System.Web;
using System.Xml;

namespace Project.Payment.Liberty
{
    public sealed class XmlApiAgent : AbstractApiAgent
    {
        public XmlApiAgent(ApiCredentials credentials)
            : base(credentials)
        {
        }

        #region IApiAgent Members      

        public override string AccountName(string accountNumber)
        {
            var request = new StringBuilder();
            request.AppendFormat("<AccountNameRequest id='{0}'>", DateTime.UtcNow.Ticks);
            request.Append(AuthToken());
            request.AppendFormat("<AccountName><AccountToRetrieve>{0}</AccountToRetrieve></AccountName>", accountNumber);
            request.Append("</AccountNameRequest>");

            var response = SendXmlRequest("/xml/accountname", request.ToString());
            return ParseAccountNameResponse(response);
        }

        #endregion

        private string AuthToken()
        {
            return string.Format(CultureInfo.InvariantCulture, "<Auth><AccountId>{0}</AccountId><ApiName>{1}</ApiName><Token>{2}</Token></Auth>",
                Credentials.AccountNumber,
                Credentials.ApiName,
                Credentials.CreateSecurityToken());
        }        

        private static string ParseAccountNameResponse(XmlDocument response)
        {
            CheckError(response);
            var name = response.SelectSingleNode("AccountNameResponse/AccountName/Name");
            if (name == null)
            {
                throw new ApiException("Invalid response format");
            }

            return name.InnerText;
        }

        private static bool HasMore(XmlDocument response)
        {
            var node = response.SelectSingleNode("HistoryResponse/Pager/HasMore");
            if (node == null)
            {
                throw new ApiException("Invalid response format");
            }

            return "true" == node.InnerText;
        }

        private static void CheckError(XmlDocument doc)
        {
            var error = doc.SelectSingleNode("//Error");
            if (error != null)
            {
                string errorCode = error.SelectSingleNode("Code").InnerText;
                string errorText = error.SelectSingleNode("Text").InnerText;
                string errorDescription = error.SelectSingleNode("Description").InnerText;
                throw new ApiException(String.Format(CultureInfo.InvariantCulture, "{0}: {1}",
                    errorText, errorDescription))
                {
                    ErrorCode = Int32.Parse(errorCode, CultureInfo.InvariantCulture)
                };
            }
        }

        private XmlDocument SendXmlRequest(string path, string requestData)
        {
            var response = SendRequest(path, string.Concat("req=", HttpUtility.UrlEncode(requestData)));
            var responseDocument = new XmlDocument();
            try
            {
                responseDocument.LoadXml(response);
            }
            catch (XmlException xex)
            {
                throw new ApiException("An error occured while parsing response XML", xex);
            }

            return responseDocument;
        }

        public override Balance Balance()
        {
            throw new NotImplementedException();
        }
    }
}
